﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace Corona
{
	/// <summary>
	/// Icon.xaml 的交互逻辑,图标类
	/// </summary>
    public partial class Icon
    {
        #region Basic Info
        /// <summary>
        /// 图标的位置，中心为原点
        /// </summary>
        public Point Position
        {
            get 
            {
                return this.GetCenterPosition(); 
            }
            set 
            { 
                this.SetPosition(value.X - this.Width / 2, value.Y - this.Height / 2); 
            }
        }

        /// <summary>
        /// 图标图片路径值
        /// </summary>
        public String Image
        {
            set 
            { 
                SetValue(ImageProperty, value); 
            }
            get 
            { 
                return (String)GetValue(ImageProperty); 
            }
        }

        /// <summary>
        /// 图标名称值
        /// </summary>
        public String Title
        {
            set 
            { 
                SetValue(TitleProperty, value); 
            }
            get 
            { 
                return (String)GetValue(TitleProperty); 
            }
        }

        /// <summary>
        /// 用于记录图标是否被选中
        /// </summary>
        public bool IsSelected
        {
            get 
            { 
                return _IsSelected; 
            }
            set
            {
                _IsSelected = value;
                if (value == true && IconOnSelect != null)
                    IconOnSelect(this, new Corona.TagPresent.IconEventArgs(this as Icon));
                else if (value == false && IconOffSelect != null)
                    IconOffSelect(this, new Corona.TagPresent.IconEventArgs(this as Icon));
            }
        }
        #endregion


        /// <summary>
        ///  跟踪当前显示的可拖动图标的数目
        /// </summary>
       // public bool toggle = false;
        static public int totalChildrenCount;
        
        /// <summary>
        /// 当前图标的最大层数
        /// </summary>
        static public int largestZIndex;

        /// <summary>
        /// 图标放大缩小时的速度
        /// </summary>
        static public double ChangeSizeSpeed = 10;

        /// <summary>
        /// 图标最大尺寸
        /// </summary>
        static public double IconMaxSize = 310;

        /// <summary>
        /// 图标最小尺寸
        /// </summary>
        static public double IconMinSize = 30;

        /// <summary>
        /// 选中后的显示的部分与图标部分的倍数
        /// </summary>
        static public double IconSelectImageSizeTiems = 1.5;

        /// <summary>
        /// 用于统计图标是否在选区中（为此图标向左发出射线与多边形相交的次数）
        /// </summary>
        public int CrossCount = 0;

        private bool _IsSelected = false;

        public event EventHandler<Corona.TagPresent.IconEventArgs> IconOnSelect;
        public event EventHandler<Corona.TagPresent.IconEventArgs> IconOffSelect;

        public bool ShowSpecialButton = true;

        public ScaleTransform IconScale = new ScaleTransform(1, 1);
        #region Drag
        /// <summary>
        /// 用于记录图像是否进行拖拽
        /// </summary>
        private bool IsDragging = false;

        /// <summary>
        /// 用于记录图像是否移动
        /// </summary>
        private bool IsImageMoved = false;

        /// <summary>
        /// 用于记录图像是否在列表之中
        /// </summary>
        //private bool IsOverListBox = false;

        /// <summary>
        /// 用于完成拖拽动作的中间变量
        /// </summary>
        private Button senderObject = new Button();

        /// <summary>
        /// 偏移量X,即鼠标在元件内部的水平位置
        /// </summary>
        private double offsetX;

        /// <summary>
        /// 偏移量Y,即鼠标在元件内部的垂直位置
        /// </summary>
        private double offsetY;

        /// <summary>
        /// 鼠标进行拖拽时的初始位置,用于检测图标是否移动
        /// </summary>
        private Point initialPos;

        /// <summary>
        /// 鼠标进行拖拽时的结束位置,用于检测图标是否移动
        /// </summary>
        private Point finalPos;
        #endregion

        #region Delegate
        /// <summary>
        /// 图标位置改变委托
        /// </summary>
        /// <param name="sender"></param>
        public delegate void IconPositionChangeHandler(object sender);

        /// <summary>
        /// 图标位置改变事件
        /// </summary>
        public event IconPositionChangeHandler IconPositionChange;

        /// <summary>
        /// 图标点击委托
        /// </summary>
        /// <param name="sender"></param>
        public delegate void BaseMouseClickHandler(object sender);

        /// <summary>
        /// 图标点击事件
        /// </summary>
        public event BaseMouseClickHandler BaseMouseClick;

        /// <summary>
        /// 图标大小改变委托
        /// </summary>
        /// <param name="sender"></param>
        public delegate void IconSizeChangeHandler(object sender);

        /// <summary>
        /// 图标大小改变事件
        /// </summary>
        public event IconSizeChangeHandler IconSizeChange;
        #endregion

        #region Properties
        /// <summary>
        /// 图标的图片,可以来源自工程内部资源,也可以是外部图片,现只提供绝对路径
        /// </summary>
        public static readonly DependencyProperty ImageProperty = DependencyProperty.Register("Image", typeof(String), typeof(Icon), new FrameworkPropertyMetadata(ImagePropertyChangeHandler));

        /// <summary>
        /// 图标的名称,显示在图标图片的下面
        /// </summary>
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(String), typeof(Icon), new FrameworkPropertyMetadata(TitlePropertyChangeHandler));

        /// <summary>
        /// 图标的图片发生变化时应进行的方法
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private static void ImagePropertyChangeHandler(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            Uri uri = new Uri((source as Icon).Image);
            BitmapImage bitmapimage = new BitmapImage(uri);
            (source as Icon).IconImage.Source = bitmapimage;
        }

        /// <summary>
        /// 图标的名称发生变化时应进行的方法
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private static void TitlePropertyChangeHandler(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            (source as Icon).IconName.Text = (source as Icon).Title;
        }

        public static readonly DependencyProperty XProperty = DependencyProperty.Register("X", typeof(double), typeof(Icon), new FrameworkPropertyMetadata(XPropertyChangeHandler));
        public static readonly DependencyProperty YProperty = DependencyProperty.Register("Y", typeof(double), typeof(Icon), new FrameworkPropertyMetadata(YPropertyChangeHandler));
        private static void XPropertyChangeHandler(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            Icon target = source as Icon;
            target.SetPosition(target.X - target.Width / 2, target.Y - target.Height / 2);
        }
        private static void YPropertyChangeHandler(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            Icon target = source as Icon;
            target.SetPosition(target.X - target.Width / 2, target.Y - target.Height / 2);
        }
        public double X
        {
            set { SetValue(XProperty, value); }
            get { return (double) GetValue(XProperty); }
        }
        public double Y
        {
            set { SetValue(YProperty, value); }
            get { return (double)GetValue(YProperty); }
        }
        /// <summary>
        /// 图标位置参数X
        /// </summary>
        private double xPosition
        {
            get;
            set;
        }

        /// <summary>
        /// 图标位置参数Y
        /// </summary>
        private double yPosition
        {
            get;
            set;
        }
        #endregion

        #region InitialIcon
        /// <summary>
        /// 默认初始化
        /// </summary>
		public Icon()
		{
			this.InitializeComponent();
            this.InitialToSelect();
            this.RenderTransform = IconScale;
            totalChildrenCount++;
            largestZIndex++;
		}

        /// <summary>
        /// 图标图片和名称初始化
        /// </summary>
        /// <param name="icon_name_value"></param>
        /// <param name="icon_image_value"></param>
        public Icon(String TitleValue, String ImageValue) : this()
        {
            this.Title = TitleValue;
            this.Image = ImageValue;
        }

        /// <summary>
        /// 图标高度和宽度初始化
        /// </summary>
        /// <param name="height"></param>
        /// <param name="width"></param>
        public Icon(double height, double width) : this()
        {
            this.Height = height;
            this.Width = width;
        }
        public Icon(Point position) : this()
        {
            this.Position = position;
        }
        /// <summary>
        /// 图标高度和宽度以及位置初始化
        /// </summary>
        /// <param name="height"></param>
        /// <param name="width"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public Icon(double height, double width, double x, double y) : this()
        {
            this.Height = height;
            this.Width = width;
            SetPosition(x, y);
        }

        /// <summary>
        /// 图标图片、名称、高度、宽度初始化
        /// </summary>
        /// <param name="icon_name_value"></param>
        /// <param name="icon_image_value"></param>
        /// <param name="height"></param>
        /// <param name="width"></param>
        public Icon(String TitleValue, String ImageValue, double height, double width) : this()
        {
            this.Title = TitleValue;
            this.Image = ImageValue;
            this.Height = height;
            this.Width = width;
        }
        #endregion

        #region Methods
        /// <summary>
        /// 设定图标位置，会发出图标位置改变的事件，实际上设定为和原来相同的位置也会发出事件，只是考虑到很少会有人设定与原来相同的位置
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        private void SetPosition(double x, double y)
        {
            xPosition = x;
            yPosition = y;

            if (IconPositionChange != null)
                IconPositionChange(this);

            Canvas.SetLeft(IconButton, xPosition);
            Canvas.SetTop(IconButton, yPosition);

            Canvas.SetLeft(OnSelectImage, xPosition - IconControl.Width * (IconSelectImageSizeTiems - 1) / 2);
            Canvas.SetTop(OnSelectImage, yPosition - IconControl.Height * (IconSelectImageSizeTiems - 1) / 2);

            Canvas.SetLeft(TextGrid, xPosition);
            Canvas.SetTop(TextGrid, yPosition + IconGrid.Height);
        }

        /// <summary>
        /// 获得图标现在的位置，以左上角为中心
        /// </summary>
        /// <returns></returns>
        private Point GetPosition()
        {
            Point position = new Point();
            position.X = xPosition;
            position.Y = yPosition;
            return position;
        }
        /// <summary>
        /// 获得图标现在的位置，以中心为中心
        /// </summary>
        /// <returns></returns>
        private Point GetCenterPosition()
        {
            Point position = new Point();
            position.X = xPosition;
            position.Y = yPosition;
            position.Offset(this.Width / 2, this.Height / 2);
            return position;
        }
        /// <summary>
        /// 鼠标按下事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MouseDownIcon(object sender, MouseButtonEventArgs e)
        {
            IsDragging = true;
            IsImageMoved = false;
            senderObject = sender as Button;

            initialPos = Mouse.GetPosition(ParentCanvas);

            offsetX = e.GetPosition(senderObject).X;
            offsetY = e.GetPosition(senderObject).Y;
            
            Canvas.SetZIndex(this, largestZIndex++);
        }

        /// <summary>
        /// 鼠标拖拽事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void MouseMoveIcon(object sender, MouseEventArgs e)
        {
            if (IsDragging)
            {
                //Canvas parentCanvas = this.Parent as Canvas;
                
                double currentX = e.GetPosition(ParentCanvas).X;
                double currentY = e.GetPosition(ParentCanvas).Y;

                Canvas.SetLeft(senderObject, currentX - offsetX);
                Canvas.SetTop(senderObject, currentY - offsetY);

                Canvas.SetLeft(OnSelectImage, currentX - offsetX - IconControl.Width * (IconSelectImageSizeTiems - 1) / 2);
                Canvas.SetTop(OnSelectImage, currentY - offsetY - IconControl.Height * (IconSelectImageSizeTiems - 1) / 2);

                Canvas.SetLeft(TextGrid, currentX - offsetX);
                Canvas.SetTop(TextGrid, currentY - offsetY + IconGrid.Height);

                xPosition = currentX - offsetX;
                yPosition = currentY - offsetY;

                if (IconPositionChange != null)
                    IconPositionChange(this);

                finalPos = Mouse.GetPosition(ParentCanvas);

                if ((Math.Abs(finalPos.X - initialPos.X) < 1) && (Math.Abs(finalPos.Y - initialPos.Y)) < 1)
                {
                    IsImageMoved = false;
                }
                else
                {
                    IsImageMoved = true;
                }
            }
        }

        /// <summary>
        /// 鼠标松开事件,可以配合IsImageMoved发出点击Click事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MouseUpIcon(object sender, MouseButtonEventArgs e)
        {
            

            IsDragging = false;

            Canvas parentCanvas = this.Parent as Canvas;
            
            //图标的活动范围,超出范围会设定位置在边缘
            if (parentCanvas != null)
            {
                if (yPosition < 0)
                {
                    SetPosition(xPosition, 0);
                }

                if (yPosition + senderObject.ActualHeight > parentCanvas.ActualHeight)
                {
                    SetPosition(xPosition, parentCanvas.ActualHeight - senderObject.ActualHeight);
                }

                if (xPosition + senderObject.ActualHeight > parentCanvas.ActualWidth)
                {
                    SetPosition(parentCanvas.ActualWidth - senderObject.ActualWidth, yPosition);
                }

                if (xPosition < 0)
                {
                    SetPosition(0, yPosition);
                }
            }
        }
        
        /// <summary>
        /// 鼠标滚轮事件,放大缩小图标
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MouseWheelIcon(object sender, MouseWheelEventArgs e)
        {
            double AddOrSub = e.Delta / Math.Abs(e.Delta);
            double ChangeValue = AddOrSub * ChangeSizeSpeed;
            if (!IsDragging)
                if (AddOrSub > 0 && this.Height <= IconMaxSize - 10 && this.Width <= IconMaxSize - 10 || AddOrSub < 0 && this.Height >= IconMinSize + 10 && this.Width >= IconMinSize + 10)
                {
                    double oldHeight = this.Height;
                    double oldWidth = this.Width;
                    this.Height += (2 * oldHeight / (oldHeight + oldWidth)) * ChangeValue;
                    this.Width += (2 * oldWidth / (oldHeight + oldWidth)) * ChangeValue;

                    OnSelectImage.Height = IconControl.Height * IconSelectImageSizeTiems;
                    OnSelectImage.Width = IconControl.Width * IconSelectImageSizeTiems;

                    this.SpecialButton.Height = this.Height / 4;
                    this.SpecialButton.Width = this.SpecialButton.Height;

                    this.CloseButton.Height = this.Height / 5;
                    this.CloseButton.Width = this.CloseButton.Height;

                    SetPosition(xPosition - ChangeValue / 2, yPosition - ChangeValue / 2);

                    if (IconSizeChange != null)
                        IconSizeChange(this);

                    Storyboard ChangeSizeShow;
                    Storyboard ChangeSizeAction;
                    if (AddOrSub > 0)
                    {
                        ChangeSizeShow = this.FindResource("AddSizeShow") as Storyboard;
                        ChangeSizeAction = this.FindResource("AddSizeAction") as Storyboard;
                        ChangeSizeShow.Begin(this);
                        ChangeSizeAction.Begin(this);
                    }
                    else if (AddOrSub < 0)
                    {
                        ChangeSizeShow = this.FindResource("SubSizeShow") as Storyboard;
                        ChangeSizeAction = this.FindResource("SubSizeAction") as Storyboard;
                        ChangeSizeShow.Begin(this);
                        ChangeSizeAction.Begin(this);
                    }
                }
        }
        #endregion
        
        /// <summary>
        /// 选中后的动作
        /// </summary>
        /// <param name="sender"></param>
        private void OnIconOnSelect(object sender, Corona.TagPresent.IconEventArgs e)
        {
            OnSelectImage.Height = IconControl.Height * IconSelectImageSizeTiems;
            OnSelectImage.Width = IconControl.Width * IconSelectImageSizeTiems;

            Canvas.SetLeft(OnSelectImage, xPosition - IconControl.Width * (IconSelectImageSizeTiems - 1) / 2);
            Canvas.SetTop(OnSelectImage, yPosition - IconControl.Height * (IconSelectImageSizeTiems - 1) / 2);

            OnSelectImage.Visibility = Visibility.Visible;

            Storyboard showSelect = this.FindResource("ShowOnSelect") as Storyboard;
            showSelect.Begin();
        }
        /// <summary>
        /// 取消选中的动作
        /// </summary>
        /// <param name="sender"></param>
        private void OnIconOffSelect(object sender, Corona.TagPresent.IconEventArgs e)
        {
            Storyboard hideSelect = this.FindResource("HideOnSelect") as Storyboard;
            hideSelect.Begin();
            hideSelect.Completed += new EventHandler((obj, ev) => { OnSelectImage.Visibility = Visibility.Hidden; });
        }

        /// <summary>
        /// 选中动作初始化
        /// </summary>
        private void InitialToSelect()
        {
            this.IconOnSelect += OnIconOnSelect;
            this.IconOffSelect += OnIconOffSelect;
        }

        private void SpecialButton_Loaded(object sender, RoutedEventArgs e)
        {
            if (ShowSpecialButton) this.SpecialButton.Visibility = Visibility.Visible;
            else this.SpecialButton.Visibility = Visibility.Hidden;

            this.SpecialButton.Height = this.Height / 4;
            this.SpecialButton.Width = this.SpecialButton.Height;
            
            this.CloseButton.Height = this.Height / 5;
            this.CloseButton.Width = this.CloseButton.Height;
        }

        private void IconButton_Click(object sender, RoutedEventArgs e)
        {
            if (!IsImageMoved)
            {
                if (BaseMouseClick != null)
                    BaseMouseClick(this);
            }
        }

        public event EventHandler CloseButtonClick;
        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            if (CloseButtonClick != null)
                CloseButtonClick(this, new EventArgs());
        }

        public event EventHandler SpecialButtonClick;
        private void SpecialButton_Click(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            if (SpecialButtonClick != null)
                SpecialButtonClick(this, new EventArgs());
        }
    }
}